package edu.unika.aifb.graphindex.importer.db;


import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

public class ConnectionPool implements Serializable{
	private static final long serialVersionUID = -8493273199212922633L;
	private static final Logger log = Logger.getLogger(ConnectionPool.class);
	private Map<String, Connection> connectionPool = new HashMap<String, Connection>();
	private List<Connection> connections = new ArrayList<Connection>();
	private Connection currentConnection;
	
	public Connection createConnection(String jdbcUrl, String user, String password, String driverName) throws SQLException{
		try {
			String connectionId = jdbcUrl + user;
			Connection conn = connectionPool.get(connectionId);
			if(conn == null || conn.isClosed()){
				if(driverName != null){
					try {
						Class.forName(driverName) ;
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
				}
				System.out.println(jdbcUrl + " "+ user + " " + password + "");
				conn = DriverManager.getConnection(jdbcUrl, user, password);
				connectionPool.put(connectionId, conn);
				connections.add(conn);
				currentConnection =  conn;
			}
			return conn;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	public Connection getConnection(String jdbcUrl, String user){
		return connectionPool.get(jdbcUrl + user);
	}
	
	public List<Connection> getConnections(){
		return new ArrayList<Connection>(connectionPool.values());
	}
	
	public ResultSet executeQuery(String sql){
		for(int i = 0; i <= connections.size(); i++){
			try {
				Statement stmt = currentConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
				return stmt.executeQuery(sql);
			} catch (SQLException e) {
				if(i == connections.size())
					return null;
				log.debug("Exception by executing "  +  sql + " on " + getConnectionURL(currentConnection));
				currentConnection = connections.get(i);
				continue;
			}
		}
		return null;
	}
	
	public ResultSet executeQuery(String sql, int maxRow){
		for(int i = 0; i <= connections.size(); i++){
			try {
				Statement stmt = currentConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
				stmt.setMaxRows(maxRow);
				return stmt.executeQuery(sql);
			} catch (SQLException e) {
				if(i == connections.size())
					return null;
				log.debug("Exception by executing "  +  sql + " on " + getConnectionURL(currentConnection));
				currentConnection = connections.get(i);
				continue;
			}
		}
		return null;
	}
	
	public void closeAllConnection(){
		for(Connection conn : connections)
			try {
				conn.close();
			} catch (SQLException e) {
				log.debug("Exception by closing connection");
			}
	}
	
	private String getConnectionURL(Connection connection){
		try {
			return connection.getMetaData().getURL();
		} catch (SQLException e) {
			log.debug("Exception by getting connection url ");
			return null;
		}
	}
}
